#include "wifi_manager.h"

// wifi_manager.h
typedef struct {
    char ssid[32];
    char password[64];
    uint8_t security;     // 加密方式
    int8_t rssi;         // 信号强度
    bool connected;      // 连接状态
} wifi_config_t;

typedef enum {
    WIFI_STATE_IDLE,
    WIFI_STATE_SCANNING,
    WIFI_STATE_CONNECTING,
    WIFI_STATE_CONNECTED,
    WIFI_STATE_DISCONNECTED,
    WIFI_STATE_ERROR
} wifi_state_t;

//初始化 WiFi：
int wifi_init(void) {
    // 初始化 WiFi 硬件
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
    
    // 设置 STA 模式
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    
    // 注册事件处理函数
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, 
                                             ESP_EVENT_ANY_ID, 
                                             &wifi_event_handler, 
                                             NULL));
    return 0;
}
//扫描附近的 WiFi：

int wifi_scan_networks(void) {
    wifi_scan_config_t scan_config = {
        .ssid = NULL,
        .bssid = NULL,
        .channel = 0,
        .show_hidden = true
    };
    
    // 开始扫描
    ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, true));
    
    // 获取扫描结果
    uint16_t ap_count = 0;
    esp_wifi_scan_get_ap_num(&ap_count);
    
    wifi_ap_record_t *ap_records = malloc(sizeof(wifi_ap_record_t) * ap_count);
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_count, ap_records));
    
    return ap_count;
}
//连接到手机热点
int wifi_connect_to_ap(const char *ssid, const char *password) {
    wifi_config_t wifi_config = {0};
    
    // 配置 WiFi 参数
    strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
    strncpy((char *)wifi_config.sta.password, password, sizeof(wifi_config.sta.password));
    
    // 设置 WiFi 配置
    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    
    // 启动连接
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_ERROR_CHECK(esp_wifi_connect());
    
    return 0;
}


//事件处理：
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
                             int32_t event_id, void *event_data) {
    switch (event_id) {
        case WIFI_EVENT_STA_START:
            // WiFi 启动完成
            break;
            
        case WIFI_EVENT_STA_CONNECTED:
            // 连接成功
            printf("Connected to AP\n");
            break;
            
        case WIFI_EVENT_STA_DISCONNECTED:
            // 连接断开，尝试重连
            esp_wifi_connect();
            printf("Retry to connect to AP\n");
            break;
            
        case IP_EVENT_STA_GOT_IP:
            // 获取到IP地址
            ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
            printf("Got IP: " IPSTR "\n", IP2STR(&event->ip_info.ip));
            break;
    }
}

//自动重连机制：
#define MAX_RETRY_COUNT 5
#define RETRY_INTERVAL_MS 5000

typedef struct {
    uint8_t retry_count;
    uint32_t last_retry_time;
    bool auto_reconnect;
} wifi_reconnect_config_t;

void wifi_reconnect_task(void *pvParameters) {
    wifi_reconnect_config_t *config = (wifi_reconnect_config_t *)pvParameters;
    
    while (1) {
        if (!wifi_is_connected() && config->auto_reconnect) {
            if (config->retry_count < MAX_RETRY_COUNT) {
                esp_wifi_connect();
                config->retry_count++;
                config->last_retry_time = xTaskGetTickCount();
            }
        }
        vTaskDelay(pdMS_TO_TICKS(RETRY_INTERVAL_MS));
    }
}

//状态监控：

void wifi_monitor_task(void *pvParameters) {
    while (1) {
        wifi_ap_record_t ap_info;
        if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
            // 监控信号强度
            printf("RSSI: %d\n", ap_info.rssi);
            
            // 如果信号太弱，可以触发重新扫描和连接
            if (ap_info.rssi < -85) {
                printf("Signal too weak, trying to find better AP\n");
                wifi_scan_networks();
            }
        }
        vTaskDelay(pdMS_TO_TICKS(10000)); // 每10秒检查一次
    }
}


//例子
void app_main(void) {
    // 初始化 NVS
    nvs_flash_init();
    
    // 初始化 WiFi
    wifi_init();
    
    // 扫描网络
    int ap_count = wifi_scan_networks();
    printf("Found %d APs\n", ap_count);
    
    // 连接到指定的手机热点
    wifi_connect_to_ap("Phone_AP", "password123");
    
    // 创建重连任务
    wifi_reconnect_config_t reconnect_config = {
        .retry_count = 0,
        .auto_reconnect = true
    };
    xTaskCreate(wifi_reconnect_task, "wifi_reconnect", 2048, 
                &reconnect_config, 5, NULL);
    
    // 创建监控任务
    xTaskCreate(wifi_monitor_task, "wifi_monitor", 2048, NULL, 5, NULL);
}


/*
关键注意事项：
电源管理
错误处理
安全性考虑
这个实现提供了基本的 WiFi 连接功能，包括：
自动扫描和连接
断线重连机制
信号强度监控
状态管理
错误处理

// 设置 WiFi 省电模式
esp_wifi_set_ps(WIFI_PS_MIN_MODEM);


// 添加额外的安全配置
wifi_config_t wifi_config = {
    .sta = {
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        .pmf_cfg = {
            .capable = true,
            .required = false
        },
    },
};


// 添加错误处理和超时机制
#define WIFI_CONNECT_TIMEOUT_MS 10000

if (wait_for_wifi_connect(WIFI_CONNECT_TIMEOUT_MS) != ESP_OK) {
    printf("Connection timeout\n");
    // 处理连接超时
}
*/


//通过APP配网方式：
// wifi_config.h
typedef struct {
    char ssid[32];
    char password[64];
} wifi_credentials_t;

// APP端发送配网信息的格式
typedef struct {
    uint8_t type;        // 消息类型
    char ssid[32];       // 热点名称
    char password[64];   // 热点密码
    uint8_t checksum;    // 校验和
} app_config_message_t;

//SmartConfig配网：
// smartconfig实现
void start_smart_config(void) {
    ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH));
    smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_smartconfig_start(&cfg));
    
    // 等待手机APP发送配网信息
    EventBits_t uxBits;
    while (1) {
        uxBits = xEventGroupWaitBits(wifi_event_group, 
                                    CONNECTED_BIT | ESPTOUCH_DONE_BIT, 
                                    true, false, portMAX_DELAY);
        if(uxBits & CONNECTED_BIT) {
            printf("WiFi Connected\n");
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            printf("SmartConfig Done\n");
            break;
        }
    }
}

//// 通过蓝牙接收WiFi信息
static void bluetooth_callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {
    if (event == ESP_SPP_DATA_IND_EVT) {
        // 解析接收到的数据
        wifi_credentials_t credentials;
        memcpy(&credentials, param->data_ind.data, sizeof(wifi_credentials_t));
        
        // 保存WiFi信息
        save_wifi_config(&credentials);
    }
}


// 解析二维码数据
typedef struct {
    char protocol[10];   // 协议类型
    char ssid[32];      // WiFi名称
    char password[64];  // WiFi密码
} qr_wifi_data_t;

bool parse_wifi_qr(const char* qr_data, wifi_credentials_t* credentials) {
    // 解析二维码数据格式：WIFI:S:<SSID>;T:<WPA|WEP>;P:<password>;;
    if (strncmp(qr_data, "WIFI:", 5) != 0) {
        return false;
    }
    
    // 解析SSID和密码
    char *ssid_start = strstr(qr_data, "S:") + 2;
    char *pass_start = strstr(qr_data, "P:") + 2;
    
    // 复制数据
    strncpy(credentials->ssid, ssid_start, 32);
    strncpy(credentials->password, pass_start, 64);
    
    return true;
}

// 创建简单的Web服务器
void start_webserver(void) {
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    
    httpd_start(&server, &config);
    
    // 注册URI处理程序
    httpd_uri_t wifi_post_uri = {
        .uri       = "/wifi/config",
        .method    = HTTP_POST,
        .handler   = wifi_config_handler,
        .user_ctx  = NULL
    };
    httpd_register_uri_handler(server, &wifi_post_uri);
}

// 处理WiFi配置请求
esp_err_t wifi_config_handler(httpd_req_t *req) {
    char content[100];
    size_t recv_size = MIN(req->content_len, sizeof(content));
    
    int ret = httpd_req_recv(req, content, recv_size);
    if (ret <= 0) return ESP_FAIL;
    
    // 解析JSON数据
    cJSON *root = cJSON_Parse(content);
    char *ssid = cJSON_GetObjectItem(root, "ssid")->valuestring;
    char *password = cJSON_GetObjectItem(root, "password")->valuestring;
    
    // 保存WiFi配置
    wifi_credentials_t credentials;
    strncpy(credentials.ssid, ssid, sizeof(credentials.ssid));
    strncpy(credentials.password, password, sizeof(credentials.password));
    
    save_wifi_config(&credentials);
    
    cJSON_Delete(root);
    return ESP_OK;
}


// 保存WiFi配置到Flash
void save_wifi_config(const wifi_credentials_t* credentials) {
    nvs_handle_t nvs_handle;
    nvs_open("storage", NVS_READWRITE, &nvs_handle);
    
    // 保存SSID和密码
    nvs_set_str(nvs_handle, "wifi_ssid", credentials->ssid);
    nvs_set_str(nvs_handle, "wifi_pass", credentials->password);
    
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
}

// 读取保存的配置
bool load_wifi_config(wifi_credentials_t* credentials) {
    nvs_handle_t nvs_handle;
    nvs_open("storage", NVS_READONLY, &nvs_handle);
    
    size_t required_size;
    if (nvs_get_str(nvs_handle, "wifi_ssid", NULL, &required_size) == ESP_OK) {
        nvs_get_str(nvs_handle, "wifi_ssid", credentials->ssid, &required_size);
        nvs_get_str(nvs_handle, "wifi_pass", credentials->password, &required_size);
        nvs_close(nvs_handle);
        return true;
    }
    
    nvs_close(nvs_handle);
    return false;
}


// 加密存储的密码
void encrypt_credentials(wifi_credentials_t* credentials) {
    uint8_t key[16] = {/* 你的加密密钥 */};
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_enc(&aes, key, 128);
    
    // 加密密码
    uint8_t encrypted[64];
    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT,
                          (uint8_t*)credentials->password,
                          encrypted);
                          
    memcpy(credentials->password, encrypted, sizeof(encrypted));
    mbedtls_aes_free(&aes);
}

/*
主要配网方式比较：
APP配网：
优点：用户体验好，可控性强
缺点：需要开发配套APP
SmartConfig：
优点：无需额外硬件，使用方便
缺点：受环境干扰大
蓝牙配网：
优点：稳定性好，安全性高
缺点：需要设备支持蓝牙
二维码配网：
优点：使用简单，用户友好
缺点：需要设备有扫码能力
Web配网：
优点：实现简单，通用性强
缺点：需要设备先建立AP热点
*/